package com.kgc.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.kgc.api.buylimit.TradeOrderApi;
import com.kgc.bean.*;
import com.kgc.config.BuyLimitConfig;
import com.kgc.service.BuyLimitService;
import com.kgc.util.RedisUtils;

import com.mysql.jdbc.log.Log;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import springfox.documentation.spring.web.json.Json;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Author：周申宇 <p>
 * @Date:2021/6/19 15:59
 * <p>
 * @Decription:  抢购业务的实现
 */
@Service
@Slf4j
public class BuyLimitServiceImpl implements BuyLimitService {

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private BuyLimitConfig buyLimitConfig;

    @Reference(timeout = 30000)
    private TradeOrderApi tradeOrderApi;

    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Override
    public boolean initProdStockToRedis(String prodId) {

        // 先从redis中，取库存
        Object prodStockNum = redisUtils.get(buyLimitConfig.getStockNumPrefix()+prodId);

        // 如果redis中没有,就把数据塞到redis中
        return prodStockNum == null && redisUtils.set(buyLimitConfig.getStockNumPrefix()+prodId,buyLimitConfig.getProdStockNum());
    }

    @Override
    public boolean checkUserActivity(Integer userId, Integer activityId) {

        if(ObjectUtils.isEmpty(redisUtils.get("user-"+activityId))){
            return false;
        }

        // 当redis中存在，需要先把添加本次活动的用户拿出来
        ArrayList<String> userIds = (ArrayList<String>) JSON.parseArray(redisUtils.get("user-"+activityId).toString(),String.class);
        // 当redis中的 list 存在用户 id ，代表用户已经添加了本次抢购活动
        if(userIds.contains(userId.toString())){
            return true;
        }
        return false;
    }

    @Override
    public boolean checkActivityDate(Integer activityId) throws ParseException {

        BuyLimitActivity buyLimitActivity = JSONObject.toJavaObject(JSON.parseObject(redisUtils.get(activityId.toString()).toString()),BuyLimitActivity.class);

        //判断日期
        log.info("开始时间{}",buyLimitActivity.getBeginTime());
        int begStaue = buyLimitActivity.getBeginTime().compareTo(simpleDateFormat.parse(simpleDateFormat.format(new Date())));
        log.info("是否大于开始时间{}",begStaue);
        int endStaue = buyLimitActivity.getEndTime().compareTo(simpleDateFormat.parse(simpleDateFormat.format(new Date())));
        log.info("是否小于结束时间{}",endStaue);
        log.info("结束时间{}",buyLimitActivity.getEndTime());
        if(endStaue == 1 && begStaue == -1){
            return true;
        }
        log.info("抢购时间已经错过");
        return false;
    }

    @Override
    public boolean lockBuyUser(String userId,String prodId) {
        // 借助redis的分布式锁，锁定用户，要使用名称空间概念
        return  redisUtils.lock(buyLimitConfig.getLockUserPrefix()+userId+":"+prodId,null,buyLimitConfig.getBuyLimitTime());
    }

    @Override
    public boolean checkProdStock(String prodId,Integer buyCount) {
        if(ObjectUtils.isEmpty(redisUtils.get(buyLimitConfig.getStockNumPrefix()+prodId))){
            return false;
        }

        // 从redis获取当前商品库存
        Object stock = redisUtils.get(buyLimitConfig.getStockNumPrefix()+prodId).toString();
        // 如果库存量大于购买量，返回true
        return stock != null && Integer.valueOf(stock.toString()) >= buyCount;
    }

    @Override
    public boolean isStock(String prodId) {

        // 直接进行上锁，（setnx,如果已经锁定，上锁失败）上锁成功，没有用户抢购，可以进行后续流程，如果上锁失败，代表有人抢购
        return !redisUtils.lock(buyLimitConfig.getStockLockPrefix()+prodId,null,buyLimitConfig.getStockLockTime());
    }

    @Override
    public void setTradeOrderNoToRedis(String tradeOrderNo, String userId) {
        redisUtils.set(tradeOrderNo,userId);
    }

    @Override
    public void createTradeOrder(User user, GoodsItemVo goodsItemVo,Integer buyCount, String tradeOrderNo) {
        // 创建订单，插入数据库，把订单状态修改为 未支付 1
        tradeOrderApi.createTradeOrder(user,goodsItemVo,buyCount,tradeOrderNo);
    }

    @Override
    public boolean deleteOrderNoByOrderNo(String tradeOrderNo) {
        // 这个是在消费者中的，如果消息队列成功，在消息删除本次订单编号
        return ObjectUtils.isEmpty(redisUtils.get(tradeOrderNo));
    }

    @Override
    public void subProStockNum(String prodId, Integer buyCount) {
        redisUtils.decr(buyLimitConfig.getStockNumPrefix()+prodId,buyCount);

    }

    public void unLockProStockLock(String prodId){
        redisUtils.delLock(buyLimitConfig.getStockLockPrefix()+prodId);
    }

    @Override
    public OrderInfo queryOrderInfoByOrderInfoId(String orderInfoId) {
        return tradeOrderApi.getOrderInfoByOrderInfoId(orderInfoId);
    }

}
